#!/usr/bin/env python3

"""
使用多种方式实现单例模式
"""

class Singleton_new_1(object):
    __instance = None

    def __new__(cls, name, age):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance


class Singleton_new_2(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.__instance = super(Singleton_new_2, cls).__new__(cls)
        return cls.__instance



class Singleton_import:

    def foo(self):
        pass

singleton_import = Singleton_import()


def singleton_deco_1(cls):
    instances = {}

    def getinstance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return getinstance

def singleton_deco_2(cls):
    _instance = cls(ip, port)

    def wrapper(*args, **kwargs):
        if args or kwargs:
            return cls(*args, **kwargs)
        return _instance
    return wrapper


class Singleton_meta(type):

    def __init__(self, *args, **kwargs):
        self.__instance = None
        super(Singleton_meta, self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(Singleton_meta, self).__call__(*args,
                    **kwargs)
        return self.__instance


ip = "3.3.3.110"
port = 3306
class Singleton_classmethod:
    __instance = None

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def instance(cls, *args, **kwargs):
        if args or kwargs:
            cls.__instance = cls(*args, **kwargs)
        return cls.__instance

def run_test():
    #  使用__new__方法实现单例模式
    sn_1_a = Singleton_new_1("molio", 25)
    sn_1_b = Singleton_new_1("lee", 25)
    print(id(sn_1_a)==id(sn_1_b))

    sn_2_a = Singleton_new_2()
    sn_2_b = Singleton_new_2()
    print(id(sn_2_a)==id(sn_2_b))

    #  从别的文件进行导包使用,从而实现单例模式
    from singleton_ways import singleton_import

    #  使用装饰器方法实现单例模式
    @singleton_deco_1
    class MyClass:
        a = 1
    myclass1 = MyClass()
    myclass2 = MyClass()
    print(id(myclass1==myclass2))

    @singleton_deco_2
    class MySQL:
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    mysql1= MySQL()
    mysql2= MySQL()
    mysql3= MySQL('3.3.3.110', 3306)
    print(id(myclass1==myclass2))
    print(mysql3, mysql3.__dict__)


    #  使用元类meatclass实现单例模式
    class Foo(object, metaclass=Singleton_meta):
        a = 1
    f1 = Foo()
    f2 = Foo()
    print(id(f1==f2))

    #  使用全局变量方式
    obj1 = Singleton_classmethod.instance(ip, port)
    obj2 = Singleton_classmethod.instance()
    obj3 = Singleton_classmethod.instance()
    print(obj1)
    print(obj2, obj2.__dict__)
    print(obj3, obj3.__dict__)


if __name__ == "__main__":
    run_test()
